 /* 
  * Copyright (C) 2012 maxim 
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
  * published by the Free Software Foundation; either version 2 of the
  * License, or (at your option) any later version.
  *
  * This program is distributed in the hope that it will be useful, but
  * WITHOUT ANY WARRANTY; without even the implied warranty of
  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  * General Public License for more details.
  *
  * You should have received a copy of the GNU General Public License
  * along with this program; if not, write to the Free Software
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
  * USA
  */

#include "user_threads.h"
#include "user_mutex.h"
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>

#include "tests.h"

static uthread_mutex_t mutex1;

int mutex_owner = 0;


/* Endurance test + test that mutexes are FIFO */

static int thread(void* arg)
{

	int i;
	for (i = 0 ; i < 10 ; i++) {
		uthread_mutex_lock(mutex1);
		msg("thread %d got mutex", uthread_self());

		assert(uthread_self() - 1 == mutex_owner);
		mutex_owner = (mutex_owner + 1) %3;


		delay(30000000, 0);
		uthread_mutex_unlock(mutex1);
	}

	msg("thread %d exits", uthread_self());
	return 0;
}


void test3()
{
	msg("\nRunning test #3...");

	assert(uthread_mutex_init(&mutex1) == MUTEX_SUCCESS);
	assert(uthread_mutex_lock(mutex1) == MUTEX_SUCCESS);

	/* Create 3 threads and let them compete for the lock */
	assert (uthread_create(thread, NULL, UTHREAD_MAX_PRIO) == 1);
	assert (uthread_create(thread, NULL, 5) == 2);
	assert (uthread_create(thread, NULL, 1) == 3);

	uthread_yield();
	uthread_mutex_unlock(mutex1);
	uthread_yield();

	assert(uthread_join(1, NULL) == UTHREAD_SUCCESS);
	assert(uthread_join(2, NULL) == UTHREAD_SUCCESS);
	assert(uthread_join(3, NULL) == UTHREAD_SUCCESS);

	assert(uthread_join(1, NULL) == UTHREAD_INVALID);
	assert(uthread_join(2, NULL) == UTHREAD_INVALID);
	assert(uthread_join(3, NULL) == UTHREAD_INVALID);

}
